
#include <string.h>
#include "hook.h"
#include <stdio.h>


//#include <stdio.h>

/*
程序会从EXTEND_ADDR中加载

把需要hook的地址改为跳转的地址
    8008D994 地址为显示文本


sanguo11的字库数据在
    大小为0x111ba0
    SAN11RES.BIN (0x1b000)
    扩展内存      92526060

    按照一个字符 0x120 大小，则
    0x111ba0 / 0x120
        =   3893  (只能存放这么多0xf35)



一般情况下
    901c5c74 一般为存储菜单显示的缓存

    8000D48C
        r5为文本头指针

8008E35C
    根据ID获得文本
    r3: 数据结构，参考8008D888 参数1
    r4: 文本id

*/

extern void JMP_FUNC(u32 func,u32 save);
static int fd_readbuf(int fd,u8*dest);
static int fd_writebuf(int fd,u8*src,int sz);
extern void icache_flush();
extern void hook_main_asm();
extern void _8000D2DC();
extern void set_hook_func();
extern void hook_exit(hook_cpu_t*cpu);

extern void* __syscalls;
static u32  ___sbrk_r(void*p,int a);

#define DEBUG *(u8*)0x80fffff0 = 1

//GB编码以0xfe,0xfe结尾
#define GB_FLAG     0xfe
#define GB_FLAG2    0xfe
char *old_text = 0;
char *old_text_isgb;
u32 old_text_code = 0;
static int is_gb(char*text){
    if(!text){
        return 0;
    }
    if(old_text==text && *(u32*)text==old_text_code){
        return (int)old_text_isgb;
    }
    old_text = text;
    old_text_code = *(u32*)text;
    text += strlen(text);
    if(text[1]==GB_FLAG2){
        return 1;
    }
    return 0;
}


#define text_buf_max 1024
typedef struct{
    int     text_num;           //当前保存文本的数量
    s32     text_offset[text_buf_max];
}extend_t;

extend_t extend_data;

// void _jmp_func(){
// #if 1
// nasm(".section	\".text\"");
// nasm(".align 2");
// nasm(".globl JMP_FUNC");
// nasm(".type	JMP_FUNC, @function");
// nasm("JMP_FUNC:");
// nasm("mtctr 3");
// nasm("lwz 3,4(4)");
// nasm("lwz 5,12(4)");
// nasm("lwz 6,16(4)");
// nasm("lwz 0,0(4)");     //lr 寄存器
// nasm("lwz 1,20(4)");    //sp 寄存器
// //作为最后一个读取
// nasm("lwz 4,8(4)");
// nasm("mtlr 0");     //设置已经的lr
// //返回到目标,以ctr寄存器返回，lr寄存器为上一个保存的地址
// //转为内部执行
// nasm("bctr ");

// //使icache失效，(执行缓存)
// nasm("icache_flush:");
// nasm("mfspr 0,1008");   //获得hid0值
// nasm("ori 0,0,1<<11");    //设置icfi
// nasm("mtspr 1008,0");
// nasm("blr");
// #endif
// }

/*
由于需要还原寄存器，所以先处理bl
*/
int __start(){
nasm(".section	\".start\"");
nasm(".align 2");
nasm(".globl _start");
nasm(".type	_start, @function");
nasm("_start:");
nasm("bl extend_func");
nasm(".section	\".text\"");
}

static void load_hook_list();

int _8000C600(int code){
    /*
    编码排放顺序
        a000 ~ dfff   (+0x3c00)
        ed00 ~ ef00   (+0x3d00)
        e000 ~ eb00   (+0x3f00)
        8100 ~ 9fff   (+0x7f00)

        GB 2312 编码范围
        B0A1 - F7FE
        0xb0-0xf7   第一个字节
        0xa1-0xfe   第二个字节


    */
    u16 *_80417080;
    #if 0
    if(code<0x8100||code>=0xa000){
        if(code<0xe000||code>0xeb00){
            code -= 0x10000;
            if(code<0xed00||code>=0xef00){
                code += 0x3c00;
            }
            else{
                code += 0x3d00;
            }
        }
        else{
            code -= 0x10000;
            code += 0x3f00;
        }
    }
    else{
        code -= 0x10000;
        code += 0x7f00;
    }
    #else
    //和上面是相同的
    if(code>=0x8100&&code<0xa000){
        code -= 0x10000;
        code += 0x7f00;
    }
    else{
        if(code>=0xe000&&code<0xeb00){
            code -= 0x10000;
            code += 0x3f00;
        }
        else{
            if(code>=0xed00&&code<0xef00){
                code -= 0x10000;
                code += 0x3d00;
            }
            else{
                code -= 0x10000;
                code += 0x3c00;
            }
        }
    }
    #endif
    return _80417080[code];
}


unsigned char test_font_data[] = {
/* D:\sanguo11\font.bin (2021/5/17 2:59:04)
   起始位置(h): 00000000, 结束位置(h): 0000011E, 长度(h): 0000011F */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x07,0xFF,0xF6,0x6A,
0x07,0xA3,0xB6,0x69,0x07,0x80,0xA6,0x69,0x07,0x80,0xA6,0x69,0x07,0x80,0xA6,0x69,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x9E,0xFF,0xFF,0x1B,0x63,0x33,0x33,
0x0E,0x20,0x00,0x00,0x2E,0x00,0x00,0x00,0x69,0x09,0xFF,0xE0,0xA5,0x09,0x73,0xE0,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x20,0x00,0x00,0xE5,0x00,0x00,0x00,
0xD2,0x00,0x00,0x00,0xD2,0x00,0x00,0x00,0xD2,0x00,0x00,0x00,0xD2,0x00,0x00,0x00,
0x07,0x80,0xA6,0x69,0x07,0x80,0xA6,0x69,0x07,0x80,0xA6,0x69,0x07,0x80,0xA6,0x69,
0x07,0x80,0xA6,0x69,0x07,0xFF,0xF6,0x69,0x07,0xA3,0x31,0x69,0x07,0x80,0x00,0x69,
0x97,0x09,0x50,0xE0,0x1E,0x09,0x50,0xE0,0x0A,0x69,0x50,0xE0,0x06,0x99,0x50,0xE0,
0x04,0xB9,0x50,0xE0,0x08,0xA9,0xFF,0xE0,0xDE,0x39,0x72,0x20,0x00,0x05,0x20,0x00,
0xD2,0x00,0x00,0x00,0xD2,0x00,0x00,0x00,0xD2,0x00,0x00,0x00,0xD2,0x00,0x00,0x00,
0xD2,0x00,0x00,0x00,0xD2,0x00,0x00,0x00,0xD2,0x00,0x00,0x00,0xD2,0x00,0x00,0x00,
0x01,0x10,0x00,0x69,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xFF,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xD2,0x00,0x00,0x00,0xE2,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,
};


static void test_font(){
    void* addr = (void*)0x925264e0; //某个文字的字模
    addr = (void*)0x925eccc0;   //'编'
    memcpy(addr,test_font_data,sizeof(test_font_data));
    // int i = 0;
    // u32 *p = (u32*)addr;
    // for(i=0;i<0x120;i+=4){
    //     *p = 0xf0ffffff;
    //     p++;
    // }
}

//__attribute__((section(".start")))
int extend_func(){
    /*
    还原被hook的函数
    */
    if(SAVE->extend_fd>0){
        //关闭已经打开的文件
        IOS_Close(SAVE->extend_fd);
        SAVE->extend_fd = 0;
    }
    __syscalls = ___sbrk_r;
    hook_cpu_t save_cpu;
    hook_cpu_t *cpu = (hook_cpu_t*)0x80ff0000;
    memcpy(&save_cpu,cpu,sizeof(*cpu)); //需要备份
    int fd = IOS_Open(HOOK_RESTORE_FILE,IPC_OPEN_READ);
    SAVE->text_fd = IOS_Open(TEXT_FILE,IPC_OPEN_WRITE); //创建文本写入文件

    //*(u32*)0x80fff000 = (void*)malloc(0x100);


    if(fd<0){
        //不存在文件
        return 0;
    }


    test_font(); //测试文字

    int read_size = 512;
    u8 *data = (u8*)SAVE->hook_func;
    u8 buf[512];

    //不知道为什么IOS_Read会限制读取位置
    #if 0
    while(1){
        int ret = IOS_Read(fd,buf,read_size);
        if(ret>0){
            memcpy(data,buf,ret);
        }
        if(ret<read_size)break;
        data += ret;
    }
    #else
    fd_readbuf(fd,data);
    #endif
    //关闭文件
    IOS_Close(fd);

    //打开字库文件
    if(SAVE->font_fd<=0){
        SAVE->font_fd = IOS_Open(FONT_FILE,IPC_OPEN_READ);
    }

    //加载id翻译
    int id_fd = IOS_Open(ID_TRANSLATE_FILE,IPC_OPEN_READ);
    if(id_fd>0){
        id_text_t *t = 0x81500000;
        t->base = t->text;
        t->end_text = t->base + fd_readbuf(id_fd,t->text);
        IOS_Close(id_fd);

        char* text = t->text;
        char* tmpbuf = (char*)t->end_text;
        //分析字符串
        int id,nid;
        char end_buf[0x20];

        sscanf(text,"[0x%X",&id);
        text = strstr(text," ");
        end_buf[sprintf(end_buf,"0x%X]",id)] = 0;
        char* end_text = strstr(text,end_buf);
        int len = 0;
        if(end_text)len = end_text - text;
        DEBUG;
        if(id<0x3000){
            t->str[id].ptr = text+1;
            t->str[id].len = len;
        }

    }

    load_hook_list();
    set_hook_func();


    icache_flush();

    /*
    执行原先程序
    */
    #if 0
    //现在执行内部函数
    int (*f)() = (void*)SAVE->hook_func;
    f(SAVE->r3,SAVE->r4,SAVE->r5,SAVE->r6);
    #endif
    //JMP_FUNC(SAVE->hook_func,(u32)SAVE);
    enum{
        hook_func_off = (int)&SAVE->hook_func - (int)SAVE,
    };

    //执行旧的代码，然后还原所有寄存器

    int ret = CALL(SAVE->hook_func,cpu->reg[3],cpu->reg[4],cpu->reg[5],cpu->reg[6],cpu->reg[7],cpu->reg[8],cpu->reg[9],cpu->reg[10]);
    cpu->reg[3] = ret;
    hook_exit(&save_cpu);
    //return (int)0x80ff0000; //cpu_t的地址
}

////////////////////////////////////////////////////////
//其他功能的函数

static int skip(char*buf,int offset);
const u8 hex[];
static int get_hook(char*buf,u32*addr,char**path);
static void* xmemset(void*a,int v,int sz);

#include "extend_func.h"


////////////////////////////////////////////////
/*
修改函数
    8008D988
        [r3+0xa2c]为保存文本数据的地址
*/


static get_font_offset(hook_cpu_t *cpu);

#include "test_text.h"

#define HOOK_1 0
char record_text_buf[10240];
int  record_text_buf_offset;
static void *strstr_end(char*a,char*b){
    while(*a){
        int i = 0;
        do{
            if(b[i]!=a[i]){
                break;
            }
            i++;
        }while(b[i]);
        if(b[i]==0){
            return a;
        }
        a++;
    }
    return 0;
}

typedef struct{
    u8 esc_[1024*4];
    int     offset;
    u8  *esc_cur;
    u8  *text;
}_esc_sys_t;
_esc_sys_t esc_sys;

hook_cpu_t* hook_main(hook_cpu_t*cpu){
    hook_cpu_t save_cpu; //有时候会遇到嵌套的hook_main调用
    int s_cpu = 0;
    #define SCPU \
        s_cpu = 1; \
        memcpy4(&save_cpu,cpu,sizeof(*cpu)); \
        cpu = &save_cpu;
    if(cpu->reg[LR]==0x800919F0+4){
        SCPU;
        int id = cpu->reg[4];
        u32 data_struct = cpu->reg[3];
        cpu->reg[3] = CALL(0x8008E35C,data_struct,id);
        if(id<0x3000){
            //可替换字符串
            id_text_t *t = 0x81500000;
            char* text = *(char**)(data_struct+0xa2c);
            int len = t->str[id].len;
            char*src = t->str[id].ptr;
            if(len>0&&src){
                memcpy(text,src,len);
                text[len] = GB_FLAG;
                text[len+1] = GB_FLAG2;
                text[len+2] = 0;
            }
        }
    }
    else if(cpu->reg[LR]==0x8008D8CC){
        //处理转义字符
        if(cpu->reg[4]>=0x20){
            cpu->reg[LR] = 0x8008D8E0;
        }
        else{
            u32 r29 = cpu->reg[29];
            char* cur_text = *((char**)(r29+0xa30));
            int off = *((char**)(r29+0xa30)) - *((char**)(r29+0xa2c));
            int text_offset = *((int*)(r29+0xa24));
            void *bak = esc_sys.esc_cur;
            esc_sys.esc_cur = 0;

            //处理转义字符
            int ret = CALL(0x8008D9A8,r29,cpu->reg[4]);

            esc_sys.esc_cur = bak;
            //
            if(ret!=0){
                //退出?
                cpu->reg[LR] = 0x8008D988;
            }
            else{
                #if 1
                if(esc_sys.esc_cur){
                    int old = *((int*)(r29+0xa24));
                    int len = old - text_offset + 1;   //转义字符长度
                    int rlen = *((char**)(r29+0xa30)) - cur_text;       //现在的位置减去上一个位置;
                    int i = 0;
                    int eoff = 0;
                    if(len==1){
                        rlen = 0;
                    }
                    //DEBUG;
                    if(rlen>0&&len>0){
                        DEBUG;
                        *((int*)(r29+0xa24)) = text_offset - 1;             //重新设置位置(包括上一个)
                        *((s16*)esc_sys.esc_cur) = off;     //转义字符的位置
                        *((s16*)(esc_sys.esc_cur+2)) = len;   //转义字符的长度
                        *((s16*)(esc_sys.esc_cur+4)) = rlen;   //转义字符替换的长度
                        esc_sys.esc_cur += 6;
                        for(i=0;i<len;i++){
                            int byte = CALL(0x8008D2BC,r29);
                            *esc_sys.esc_cur = byte;
                            esc_sys.esc_cur++;
                            off++;
                        }

                        *((int*)(r29+0xa24)) = old;
                        *((s16*)esc_sys.esc_cur) = -1;     //把下一个转义字符的位置设置为0
                    }
                }
                #endif
                cpu->reg[LR] = 0x8008D970;
            }
        }
    }
    else if(cpu->reg[LR]==0x8008D994){
        SCPU;
        //0x8008D994地址的数据
        //执行外部函数
        //有时候需要备份cpu,防止递归调用

        #if 1
        //导出文本模式
        SAVE->lock = 3; //关闭导出文本模式
        if(SAVE->lock==0){      //防止递归调用
            SAVE->lock++;
            int fd = IOS_Open(ALLID_TEXT_FILE,IPC_OPEN_WRITE);
            int i;
            static u8 write_text_buf[1024 + 0x40];  //包括 [0x.. 0x..]

            if(fd>0){
                int offset = 0;
                for(i=1;i<0xea60;i++){     //最大是0xea60?
                    //
                    esc_sys.esc_cur = esc_sys.esc_;
                    *(s16*)esc_sys.esc_cur = -1;
                    esc_sys.text = *((char**)(cpu->reg[3]+0xa2c));
                    CALL(0x8008E35C,cpu->reg[3],i);
                    esc_sys.esc_cur = 0;
                    char* text = *((char**)(cpu->reg[3]+0xa2c));
                    int len = strlen(text);

                    char head[0x10];
                    int off = xsprintf(head,"[0x%x ",i);

                    #define write_ch(n) \
                        write_text_buf[offset++] = n; \
                        if(offset+1>=1024){ \
                            fd_writebuf(fd,write_text_buf,1024); \
                            offset = 0; \
                        }

                    #define write_str(t,_len) \
                        {   char* wstr = t; \
                            int len = _len; \
                            while(offset+len>1024){ \
                                /*先写入offset的数据*/ \
                                if(offset) \
                                    fd_writebuf(fd,write_text_buf,offset); \
                                offset = 0; \
                                /*然后判断len是否大于1024*/ \
                                if(len>1024){ \
                                    fd_writebuf(fd,wstr,1024); \
                                    wstr += 1024; \
                                    len -= 1024; \
                                } \
                            } \
                            if(len>0){ \
                                memcpy(write_text_buf+offset,wstr,len); \
                                offset += len; \
                            } \
                        }
                    write_str(head,off);

                    int read_off;
                    int esc_idx = 0;
                    u8 *esc_data = esc_sys.esc_;
                    int esc_off = *((s16*)(esc_data + 0));
                    if(0){
                        //没有转义字符
                        esc_off = -1;  //
                    }
                    int esc_len =  *((s16*)(esc_data + 2));
                    int esc_rlen = *((s16*)(esc_data + 4));
                    esc_data += 6;

                    for(read_off=0;read_off<len;read_off++){
                        if(read_off==esc_off){
                            //复制
                            int nbyte = 0;
                            for(nbyte=0;nbyte<esc_len;nbyte++){
                                if(esc_data[nbyte]=='\x02'&&esc_data[nbyte+1]=='\x96'){
                                    write_ch('\x1b');
                                    write_ch('[');
                                    nbyte += 1;
                                }
                                else{
                                    int byte = esc_data[nbyte];
                                    write_ch('\\');
                                    write_ch('x');
                                    write_ch(itoh[(byte>>4)&0xf]);
                                    write_ch(itoh[byte&0xf]);
                                }
                            }

                            read_off += esc_len - 1;    //下一个循环会+1
                            //下一个数据头
                            esc_data += esc_len;
                            //下一个
                            esc_off =  *((s16*)(esc_data + 0));
                            esc_len =  *((s16*)(esc_data + 2));
                            esc_rlen = *((s16*)(esc_data + 4));
                            esc_data += 6;
                        }
                        else{
                            write_ch(text[read_off]);
                        }
                    }
                    off = xsprintf(head," 0x%x]\n",i);
                    write_str(head,off);

                    *((int*)(cpu->reg[3]+0xa3c)) = 0;       //如果不为0，则退出解码
                }
            }
            IOS_Close(fd);
            SAVE->lock++;
        }

        if(SAVE->lock){
            CALL(0x8008D340,cpu->reg[3],0);
            char* text = *((char**)(cpu->reg[3]+0xa2c));
            //int text_offset = *((int*)(cpu->reg[3]+0xa24));
        }

        #else

        CALL(0x8008D340,cpu->reg[3],0);
        char* text = *((char**)(cpu->reg[3]+0xa2c));
        int text_offset = *((int*)(cpu->reg[3]+0xa24));



        int i;
        for(i=0;i<extend_data.text_num;i++){
            if(extend_data.text_offset[i]==text_offset){
                break;
            }
        }

        if((i>=extend_data.text_num) && (SAVE->text_fd>0)){
            #if 0
            int len = strlen(text);
            text[len] = '\n';   //换行
            //IOS_Write(SAVE->text_fd,text,len+1);
            fd_writebuf(SAVE->text_fd,text,len+1);
            text[len] = 0;  //结束
            #else

            int offset = xsprintf(text_buf,"[0x%X] %s\n",text_offset,text);
            fd_writebuf(SAVE->text_fd,text_buf,offset);
            extend_data.text_offset[extend_data.text_num++] = text_offset;
            int i = 0;
            #endif
        }

        for(i=0;i<text_list_num;i++){
            if(text_offset==text_list[i].offset){
                //比较相同
                int offset = xsprintf(text,"%s",text_list[i].text);
                //*(u8*)0x80fffff0 = 1;       //调试
                text[offset] = GB_FLAG;
                text[offset+1] = GB_FLAG2;
                text[offset+2] = 0;
            }
        }
        #endif


    }

    //修改字模获得偏移
    else if(
        cpu->reg[LR]==0x8000D304
    ||cpu->reg[LR]==0x8000D88C||cpu->reg[LR]==0x8026E520){
        SCPU;
        //其实只有一个参数

        /*
        由于最多使用
        0x111ba0 / 0x120
            =   3893  (只能存放这么多0xf35)
        当同一个屏幕，应该不会同时显示超过255个文字吧
            所以把
                0xe30 ~ 0xf35 被设置为临时文字显示
        */
        #if 1
        get_font_offset(cpu);
        #else
        cpu->reg[3] = CALL(0x8000C600,cpu->reg[3],cpu->reg[4]);
        if(cpu->reg[3]==0xffff){
            cpu->reg[3] = 0x386;        //'凶'
        }
        #endif
    }

    //需要修改判断编码长度
    else if(
        cpu->reg[LR]==(0x8000D5C4+4)||
        cpu->reg[LR]==(0x8000CE38+4)||
        cpu->reg[LR]==(0x8000CED4+4)||
        cpu->reg[LR]==(0x8000D184+4)||
        cpu->reg[LR]==(0x8000D85C+4)
    ){
        SCPU;
        char* text;
        u32 param;
        param = cpu->reg[PARAM];
        if(cpu->reg[LR]==(0x8000CE38+4)){
            //8000CE38
            text = (char*)cpu->reg[PARAM];
            param = *text;
        }
        else if(cpu->reg[LR]==(0x8000CED4+4)){
            text = *(char**)(cpu->reg[SP]+8);
        }
        else if(cpu->reg[LR]==(0x8000D184+4)){
            text = (char*)(cpu->reg[24]);
        }
        else if(cpu->reg[LR]==(0x8000D85C+4)){
            text = (char*)(cpu->reg[31]);
        }
        else{
            //8000D5C4
            text = *(char**)(cpu->reg[SP]+0x28);
        }

        char* flg = text + strlen(text);    //如果是gbk,一般会在文本结束添加 \x00,\xfe
        flg -= 2;
        if(flg[0]==GB_FLAG&&flg[1]==GB_FLAG2){
            //GB编码未初始化
            flg[0] = 0;
        }
        else{
            flg += 2;   //可能已经初始化
        }

        //u32 param1 = cpu->reg[PARAM];
        // if((u32)text==0x901c517c+2){
        //     *(u8*)0x80fffff0 = 1;       //调试
        // }

        if(
            flg[1]==GB_FLAG2 //只需要存在的标识符
        ){
            //GBK
            u8 byte1 = text[0];
            u8 byte2 = text[1];
            #if 0
            if(byte1>=0xb0&&byte1<=0xf7){
                cpu->reg[RESULT] = 1;
            }
            else{
                cpu->reg[RESULT] = 0;
            }
            #else
            //GBK混合这shift-jis?
            if(byte1>=0x81&&byte1<=0xf7){
                cpu->reg[RESULT] = 1;
            }
            else{
                cpu->reg[RESULT] = 0;
            }
            #endif
        }
        else{
            #if HOOK_1
            if(cpu->reg[LR]==(0x8000CE38+4)){
                cpu->reg[RESULT] = CALL(0x8000CE5C,param);
            }
            #else
            cpu->reg[RESULT] = CALL(0x8000CE5C,param);
            #endif
        }
    }

    //所有显示文本都会从8000D4A0
    else if(cpu->reg[LR]==0x8000D4C4+4){
        SCPU;
        char*text = (char*)cpu->reg[5];
        if(SAVE->other_text_fd<=0){
            SAVE->other_text_fd = IOS_Open(ALL_TEXT_FILE,IPC_OPEN_WRITE);
        }

        if(text){
            int len = strlen(text);
            if(!strstr_end(record_text_buf,text)){
                //未找到
                memcpy(record_text_buf+record_text_buf_offset,text,len);
                record_text_buf_offset += len;
                text[len] = '\n';
                fd_writebuf(SAVE->other_text_fd,text,len+1);
                text[len] = 0;
            }
            // text[0] = '\xb0';
            // text[1] = '\xa2';
            // text[2] = GB_FLAG;
            // text[3] = GB_FLAG2;
            // text[4] = 0;
        }


        if(cpu->reg[5]==0){
            cpu->reg[LR] = 0x8000D738;
        }
    }

    // if(s_cpu){
    //     memcpy4(cpu,&save_cpu,sizeof(save_cpu));
    // }
    if(s_cpu){
        hook_exit(cpu);
    }
    return cpu;
}

void set_hook_func(){
    hook_addr(0x8008D990,&hook_main_asm);

    //修改获得字模偏移的程序
    //8000D304,8000D88C,8026E520
    hook_addr(0x8000D300,&hook_main_asm);
    hook_addr(0x8000D888,&hook_main_asm);
    hook_addr(0x8026E51c,&hook_main_asm);

    //修改获得判断编码长度
    #if !HOOK_1
    hook_addr(0x8000D5C4,&hook_main_asm);
    hook_addr(0x8000CED4,&hook_main_asm);
    hook_addr(0x8000D184,&hook_main_asm);
    hook_addr(0x8000D85C,&hook_main_asm);
    #else
    //和以上是等价的，不过是在执行该函数后，才执行hook
    //不用执行8000CE5C
    hook_b(0x8000CE98,&hook_main_asm);
    #endif
    hook_addr(0x8000CE38,&hook_main_asm);
    hook_nop(0x8000CE38+4);

    hook_b(0x8000D2DC,_8000D2DC);

    //修改所有文本都经过
    hook_main;
    hook_addr(0x8000D4C4,&hook_main_asm);

    //转义字符
    hook_addr(0x8008D8C8,&hook_main_asm);

    //根据ID获得文本
    hook_addr(0x800919F0,&hook_main_asm);
}

void __8000D2DC(){

nasm(".section	\".text\"");
nasm(".align 2");
nasm(".globl _8000D2DC");
nasm(".type	_8000D2DC, @function");
nasm("_8000D2DC:");
    //处理写入文本
    nasm("mr 0,2");
    nasm("lis 2,0x80ff");
    nasm("ori 2,2,0xffe0");

    nasm("stw 24,0(2)");

    // nasm("lis 1,0x8000");
    // nasm("li 0,0xde20")
    // //nasm("ori 1,0xD2E0");
    // nasm("mtctr 1");
    nasm("mr 2,0");

    //跳回去
    nasm("lbz 0,0(24)");
    nasm("b _8000D2E0");
}

//////////////////////////////////////////////////
//引用标准库，需要自己重新写个新的申请库
#include <stdlib.h>
#include <malloc.h>

/*
设置__syscalls为本函数
*/

typedef struct{
    u8 *next;
}_alloc_t;

_alloc_t *__alloc = (_alloc_t*)(0x81500000 - 4);

extern void* __syscalls;

static u32  ___sbrk_r(void *p,int a){
    struct _reent *ptr = p;
    if(!a){
        return 0;
    }
    //申请内存
    //内存应该从0x81500000开始申请
    if(__alloc->next==0){
        __alloc->next = (u8*)0x81500000;
    }
    u32 ret = (u32)__alloc->next;
    a = a + (ret % 0x400);
    __alloc->next += a;         //要隔开一个数据
    return ret;
}


